﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using SimpleData.ObjectModel;

namespace SimpleData.Infrastructure.Validation
{
	/// <summary>
	/// Resultado da validação 
	/// </summary>
	public class EntityValidationResult
	{
		private bool forcedAsValid = false;

		/// <summary>
		/// 
		/// </summary>
		public EntityValidationResult( object instance )
			: this( instance, Enumerable.Empty<MessageItem>() )
		{ }

		/// <summary>
		/// 
		/// </summary>
		/// <param name="errors"></param>
		public EntityValidationResult( object instance, IEnumerable<MessageItem> errors )
		{
			if ( instance == null )
				throw new ArgumentNullException( "instance" );

			this.Instance = instance;
			this.Data = new Dictionary<string, object>( StringComparer.CurrentCultureIgnoreCase );
			this.Info = new List<MessageItem>();
			this.Errors = new List<MessageItem>();
			this.InnerResults = new List<EntityValidationResult>();

			if ( errors != null )
				this.Errors.AddRange( errors );
		}

		/// <summary>
		/// Obtém a lista de dados adicionais que necessitam ser passados ou informados para a tela
		/// </summary>
		public Dictionary<string, object> Data
		{
			get;
			private set;
		}

		/// <summary>
		/// Obtém a lista de informações que devem ser exibidas para o usuário
		/// </summary>
		public List<MessageItem> Info
		{
			get;
			private set;
		}

		/// <summary>
		/// Obtém a lista com as mensagens de erros que devem ser exibidas para o usuário
		/// </summary>
		public List<MessageItem> Errors
		{
			get;
			private set;
		}

		/// <summary>
		/// Obtém a lista de mensagens de erros que aconteceram nas entidades filhas
		/// </summary>
		public List<EntityValidationResult> InnerResults
		{
			get;
			private set;
		}

		/// <summary>
		/// Obtém o objeto que foi validado
		/// </summary>
		public object Instance
		{
			get;
			private set;
		}

		/// <summary>
		/// Indica se está tudo correto
		/// </summary>
		public bool IsValid
		{
			get
			{
				return this.forcedAsValid || this.Errors.Count == 0;
			}
		}

		/// <summary>
		/// Força o resultado como válido, mesmo se tiver mensagens de erro
		/// </summary>
		public void SetAsValid()
		{
			this.forcedAsValid = true;
		}

		/// <summary>
		/// Realiza a inclusão dos valores de <paramref name="otherResult"/>
		/// nesse resultado
		/// </summary>
		/// <param name="otherResult"></param>
		public void Include( EntityValidationResult otherResult )
		{
			this.InnerResults.Add( otherResult );
		}

		public void Include( IEnumerable<EntityValidationResult> results )
		{
			this.InnerResults.AddRange( results );
		}

		#region [ class MessageItem ]

		/// <summary>
		/// Representa uma mensagem que deve ser exibida para o usuário
		/// </summary>
		public class MessageItem
		{
			public MessageItem()
				: this( null, String.Empty )
			{ }

			public MessageItem( IDataObjectName name, string message )
			{
				this.Name = name;
				this.Message = message;
			}

			/// <summary>
			/// Obtém ou define o nome do objeto que foi validado
			/// </summary>
			public IDataObjectName Name
			{
				get;
				set;
			}

			/// <summary>
			/// Obtém o tipo do objeto
			/// </summary>
			public char DataObjectType
			{
				get;
				set;
			}

			/// <summary>
			/// Obtém ou define a mensagem que deve ser exibida para o usuário
			/// </summary>
			public string Message
			{
				get;
				set;
			}
		}

		#endregion
	}
}
